package cn.com.bluemoon.daps.sync.core.sync.sql.mysql;

import cn.com.bluemoon.daps.model.entity.DapDataModelSubordinateKey;
import cn.com.bluemoon.daps.model.entity.DapDataModelTable;
import cn.com.bluemoon.daps.model.entity.DapDataModelTableField;
import cn.com.bluemoon.daps.sync.core.sync.sql.DdlSql;
import cn.com.bluemoon.daps.sync.core.sync.sql.IBmSql;
import cn.com.bluemoon.daps.sync.core.sync.sql.SqlStrBuilder;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * @author Jarod.Kong
 * @date 2021-06-06 10:11
 **/
@Data
@Builder
@AllArgsConstructor
public class MysqlCreateTableSql extends DdlSql {
    private boolean ifNotExists = false;
    private DapDataModelTable table;
    private List<DapDataModelTableField> fields;
    private List<DapDataModelSubordinateKey> indexes;
    private IBmSql bmSql;

    public MysqlCreateTableSql() {
        this.bmSql = new MysqlDdlSql();
    }

    private List<MysqlColumnDefinition> toMysqlColumnDefinitions() {
        if (fields == null) {
            return Collections.emptyList();
        }
        return fields.stream().map(this::getMysqlColumnDefinition).collect(Collectors.toList());
    }

    @Override
    public String toString() {
        List<String> tableSql = createTableSql();
        return String.join(";\n", tableSql);
    }


    public List<String> getCreateTableSql() {
        return createTableSql();
    }

    /**
     * 构建建表sql
     *
     * @return s
     */
    public List<String> createTableSql() {
        List<String> sql = new ArrayList<>();
        if (table == null) {
            return Collections.emptyList();
        }
        if (fields == null || fields.isEmpty()) {
            return Collections.emptyList();
        }
        SqlStrBuilder sb = new SqlStrBuilder();
        sb.append("create table").appendWs();
        if (ifNotExists) {
            sb.appendWS("if not exists");
        }
        sb.appendBQ(table.getEngName()).appendWs();
        sb.append("(");
        // 增加主键为自增且有自增值的sql
        /*
          2021/8/5 组合主键 eg:
          CREATE TABLE `xxx`
          (
              `role_id` int(8) NOT NULL COMMENT '角色ID',
              `menu_id` int(8) NOT NULL COMMENT '菜单ID',
              PRIMARY KEY (`role_id`, `menu_id`)
          ) COMMENT '角色权限'
         */
        List<MysqlColumnDefinition> columns = toMysqlColumnDefinitions();
        List<MysqlColumnDefinition> primaryKeyCols = columns.stream().filter(MysqlColumnDefinition::isPrimaryKey).collect(Collectors.toList());
        String primaryKeyStr = null;
        if (!primaryKeyCols.isEmpty()) {
            // 设置为primary key = false，其他属性不变，独立生成一行primary key(field_names)
            String primaryFieldNames = primaryKeyCols.stream().map(c -> {
                c.setPrimaryKey(false);
                return c.getColumnName();
            }).collect(Collectors.joining("`,`"));
            primaryKeyStr = String.format("primary key (`%s`)", primaryFieldNames);
        }
        String cols = columns.stream().map(MysqlColumnDefinition::toString).collect(Collectors.joining(", "));
        sb.append(cols);
        if (primaryKeyStr != null) {
            sb.append(",").append(primaryKeyStr);
        }
        sb.append(")").appendWs();
        Optional<DapDataModelTableField> autoIncOpt = fields.stream().filter(d -> d.getAutoIncrement() != null && d.getAutoIncrement() == 1).findFirst();
        autoIncOpt.filter(d -> d.getAutoIncrDefaultValue() != null).map(DapDataModelTableField::getAutoIncrDefaultValue).ifPresent(autoIncrVal -> sb.appendWS("auto_increment").append(autoIncrVal).appendWs());
        if (table.getName() != null) {
            sb.appendWS("comment").appendSQ(formatComment(table.getName()));
        }
        sql.add(sb.toString());
        if (indexes != null && !indexes.isEmpty()) {
            if (bmSql == null) {
                bmSql = new MysqlDdlSql();
            }
            indexes.stream().map(i -> bmSql.createIndex(table, i)).filter(StringUtils::isNotBlank).forEach(sql::add);
        }
        return sql;
    }
}
